package com.adjaisd.scarecrow.controller;

import com.adjaisd.scarecrow.common.result.Result;
import com.adjaisd.scarecrow.common.utils.jwt.JwtUtils;
import com.adjaisd.scarecrow.common.utils.mqtt.EmqClient;
import com.adjaisd.scarecrow.dto.AlarmMsg;
import com.adjaisd.scarecrow.entity.Device;
import com.adjaisd.scarecrow.entity.Quota;
import com.adjaisd.scarecrow.service.*;
import com.adjaisd.scarecrow.vo.*;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author adjaisd
 * @since 2022-03-27
 */
@RestController
@RequestMapping("/device-status")
public class DeviceStatusController {

    @Autowired
    UserService userService;

    @Autowired
    DeviceService deviceService;

    @Autowired
    DeviceStatusService deviceStatusService;

    // 设置设备状态
    @ApiOperation(value = "设置设备状态")
    @ApiImplicitParam(name = "deviceVO", required = true, value = "设备状态信息", paramType = "body", dataType = "json")
    @RequestMapping(value = "/status", method = RequestMethod.POST)
    public Result setStatus(HttpServletRequest request, @RequestBody DeviceVO deviceVO) {
        String token = request.getHeader("X-token");
        Claims claims = JwtUtils.getMembers(token);
        long userId = Long.parseLong(claims.get("id").toString());

        Device device = deviceService.getDeviceByNumberUID(deviceVO.getNumber(), userId);
        if (device == null) return Result.fail().code(400).message("不存在该设备");

        if (deviceStatusService.setStatus(device.getId(), deviceVO.getStatus()))
            return Result.succ().code(200).message("修改设备状态成功");
        else
            return Result.fail().code(400).message("修改设备状态失败");
    }

    // 设置设备标签
    @ApiOperation(value = "设置设备标签")
    @ApiImplicitParam(name = "deviceVO", required = true, value = "设备状态信息", paramType = "body", dataType = "json")
    @RequestMapping(value = "/tag", method = RequestMethod.POST)
    public Result setTag(HttpServletRequest request, @RequestBody DeviceVO deviceVO) {
        String token = request.getHeader("X-token");
        Claims claims = JwtUtils.getMembers(token);
        long userId = Long.parseLong(claims.get("id").toString());

        Device device = deviceService.getDeviceByNumberUID(deviceVO.getNumber(), userId);
        if (device == null) return Result.fail().code(400).message("不存在该设备");

        if (deviceStatusService.updateTag(device.getId(), deviceVO.getTag()))
            return Result.succ().code(200).message("修改设备标签成功");
        else
            return Result.fail().code(400).message("修改设备标签失败");
    }

    // 分页查询设备
    @ApiOperation(value = "分页查询设备")
    @ApiImplicitParam(name = "deviceVO", required = true, value = "设备状态信息", paramType = "body", dataType = "json")
    @RequestMapping(value = "/page", method = RequestMethod.POST)
    public Result findPage(HttpServletRequest request, @RequestBody Map<String, String> map) {
        String token = request.getHeader("X-token");
        Claims claims = JwtUtils.getMembers(token);
        long userId = Long.parseLong(claims.get("id").toString());

        String number = "";
        String tag = "";
        long page = 1L, pageSize = 10L;
        try {
            if (map.containsKey("page")) page = Long.parseLong(map.get("page"));
            if (map.containsKey("pageSize")) pageSize = Long.parseLong(map.get("pageSize"));
            if (map.containsKey("number")) {
                number = map.get("number");
                Device device = deviceService.getDeviceByNumber(Long.valueOf(number));
                if (!device.getOwnerId().equals(userId))    // 检测是否拥有者
                    return Result.fail().code(400).message("没有该设备");
            }
            if (map.containsKey("tag")) tag = map.get("tag");
        } catch (Exception e) {
            return Result.fail().code(400).message("参数错误");
        }
        Pager<DeviceStatusVO> pager = deviceStatusService.queryPage(userId, page, pageSize, number, tag, -1);
        return Result.succ().code(200).data("pager", pager).message("分页查询设备成功");
    }

    // 监测设备断联
    @ApiOperation(value = "webhook目标，监测设备连接与断开")
    @ApiImplicitParam(name = "param", required = true, value = "设备信息", paramType = "body", dataType = "json")
    @RequestMapping(value = "/action", method = RequestMethod.POST)
    public void clientAction(@RequestBody Map<String, String> param) {
        System.out.println("ActionParam = " + param);
        String clientId = param.get("clientid");  // 格式: device-${number}
        String username = param.get("username");

        if (clientId.startsWith("monitor")) return; // 忽略系统订阅主题
        String number = null;
        try {
            String[] split = clientId.split("-");
            number = split[split.length - 1];
        } catch (Exception e) {
            System.out.println("非设备断连请求 = " + clientId);
            return;
        }
        Device device = deviceService.getDeviceByNumber(Long.valueOf(number));

        if (device == null || !username.equals(device.getName()))
            return;
        Long userId = device.getOwnerId();
        String email = userService.getUserById(userId).getEmail();

        if (param.get("action").equals("client_connected")) { //如果是联网
            deviceStatusService.updateOnLineByID(device.getId(), true);
            onlineTransfer(email, number, true);//联网通知
        }
        if (param.get("action").equals("client_disconnected")) { //如果是断网
            deviceStatusService.updateOnLineByID(device.getId(), false);
            onlineTransfer(email, number, false);//断网通知
        }
    }

    @Autowired
    MailService mailService;

    @Autowired
    EmqClient emqClient;

    // 设备断联通过邮件通知所有者
    private void onlineTransfer(String email, String number, Boolean online) {
        System.out.println("所有者 email = " + email);
        if (Strings.isNullOrEmpty(email)) return;
        String subject, content;
        if (!online) {
            subject = "设备断网通知";
            content = String.format("设备(number:%s)下线", number);
            // disconnectionAlarm;
            if (number.startsWith("webclient") || number.startsWith("monitor"))
                return;
            AlarmMsg alarmMsg = new AlarmMsg();
            alarmMsg.setDeviceId(number);
            alarmMsg.setLevel(1);
            alarmMsg.setOnline(false);
            alarmMsg.setAlarmName("设备断网");
            alarmMsg.setAlarm(true);
            //发送到emq
            emqClient.publish("/device/alarm", JSON.toJSONString(alarmMsg), 2);
        } else {
            subject = "设备联网通知";
            content = String.format("设备(number:%s)上线", number);
        }
        mailService.sendSimpleMail(email, subject, content);
    }

    // 查询设备详细状态
    @ApiOperation(value = "分页查询设备-指标-报警信息")
    @ApiImplicitParam(name = "map", required = true, value = "设备信息", paramType = "body", dataType = "json")
    @RequestMapping(value = "/quota-data", method = RequestMethod.POST)
    @ResponseBody
    public Result queryQuotaData(HttpServletRequest request, @RequestBody Map<String, String> map) {
        String token = request.getHeader("X-token");
        Claims claims = JwtUtils.getMembers(token);
        long userId = Long.parseLong(claims.get("id").toString());

        String number = "";
        String tag = "";
        int state = -1; // 默认状态无限制：在线且开启，离线或关闭，一般报警，严重报警
        long page = 1L, pageSize = 10L;
        try {
            if (map.containsKey("page")) page = Long.parseLong(map.get("page"));
            if (map.containsKey("pageSize")) pageSize = Long.parseLong(map.get("pageSize"));
            if (map.containsKey("number")) {
                number = map.get("number");
                Device device = deviceService.getDeviceByNumber(Long.valueOf(number));
                if (!device.getOwnerId().equals(userId))    // 检测是否拥有者
                    return Result.fail().code(400).message("没有该设备");
            }
            if (map.containsKey("tag")) tag = map.get("tag");
            if (map.containsKey("state")) state = Integer.parseInt(map.get("state"));
            Pager<DeviceQuotaAlarmVO> pager = deviceStatusService.queryDeviceQuotaAlarm(userId, page, pageSize, number, tag, state);
            return Result.succ().data("pager", pager).message("查询设备状态成功");
        } catch (Exception e) {
            System.out.println(e);
            return Result.fail().code(400).message("参数错误");
        }
    }

    @Autowired
    QuotaService quotaService;

    @ApiOperation(value = "更新设备指标")
    @ApiImplicitParam(name = "map", required = true, value = "设备指标信息", paramType = "body", dataType = "json")
    @RequestMapping(value = "/update-devicequota", method = RequestMethod.POST)
    @ResponseBody
    public Result updateDeviceQuota(HttpServletRequest request, @RequestBody Map<String, String> map) {
        String token = request.getHeader("X-token");
        Claims claims = JwtUtils.getMembers(token);
        long userId = Long.parseLong(claims.get("id").toString());

        try {
            String quotaId = map.get("id");
            String unit = map.get("unit");
            String webhook = map.get("webhook");
            String reference = map.get("reference");
            Quota quota = quotaService.getById(quotaId);
            if (quota == null || quota.getCreateTime() == 0L || quota.getOwnerId() != userId)
                return Result.fail().code(400).message("不存在该指标");
            quota.setUnit(unit);
            quota.setWebhook(webhook);
            quota.setReference(reference);
            quotaService.updateById(quota);
            return Result.succ().code(200).message("更新成功");
        } catch (Exception e) {
            return Result.succ().code(400).message("参数错误");
        }
    }
}